package net.ytbolg.mcxa;

import net.ytbolg.mcxa.util.DownLoadURL;
import net.ytbolg.mcxa.LangAndConfig.LangFile;
import net.ytbolg.mcxa.LangAndConfig.Config;
import net.ytbolg.mcxa.LangAndConfig.Lang;
//import org.apache.tools.zip.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import static net.ytbolg.mcxa.LauchInfoWindow.jo;
import static net.ytbolg.mcxa.LauchInfoWindow.version;
import net.ytbolg.mcxa.Launcher.GameInfo;
import static net.ytbolg.mcxa.Launcher.GameInfo.tpf;
import net.ytbolg.mcxa.Launcher.GameInfoGet;
import net.ytbolg.mcxa.Launcher.MakeCmd;
//import static net.ytbolg.mcxa.MCLaucherXA.l;
import net.ytbolg.mcxa.util.OutKeeper;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Ytong
 */
public class LauchInfoWindow extends javax.swing.JFrame {
    
    net.ytbolg.mcxa.Output.Logger l = new net.ytbolg.mcxa.Output.Logger(0);
    public static JTextArea jta;
    public static Downloader d;
    static JSONObject jo;
    static String lib;
    Thread unzip = new Thread(new unZipThread());
    Thread download = new Thread(new DownloadThread());
    boolean downok, unok = false;
    public static String version = "";

    /**
     * Creates new form LauchInfoWindow
     */
    public LauchInfoWindow() {
        initComponents();
        jta = jTextArea1;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("启动中");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });

        jTextArea1.setEditable(false);
        jTextArea1.setColumns(20);
        jTextArea1.setFont(new java.awt.Font("微软雅黑", 0, 13)); // NOI18N
        jTextArea1.setRows(5);
        jScrollPane1.setViewportView(jTextArea1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
        // TODO add your handling code here:
        setTitle(Lang.getLang("Lauch_Title"));
        try {
            //  jTextArea1.setText("什么破鸡巴语言1");
            unZipThread.j = jTextArea1;
            //  jTextArea1.setText("什么破鸡巴语言2");
            jTextArea1.setLineWrap(true);
            // jTextArea1.setText("什么破鸡巴语言3");
            //  System.out.println(jList1.getSelectedValue().toString());
            //    String version = MCLaucherXA.jList1.getSelectedValue().toString();

            lib = GameInfoGet.libstotruedir(GameInfoGet.getLibs(version));
            /*  if (System.getProperty("os.name").contains("Linux")||System.getProperty("os.name").contains("Mac")) {
             msg("检测到运行非Win系统，正在加权限");
             String tmp[] = lib.split(";");
             for (int g = 0; g < tmp.length; g++) {
             Runtime.getRuntime().exec("chmod 777 " + tmp[g]);
             }}*/
//jTextArea1.setText("什么破鸡巴语言4");
            jTextArea1.setText("MCLauncherXA " + LangFile.Version);
            msg(Lang.getLang("Lauch_VersionToLauch") + version);
            msg(Lang.getLang("Lauch_UserName") + GameInfo.UserName);
            // msg();
            new net.ytbolg.mcxa.Output.Logger(0).Log("Selected version:" + version + "\n" + "username:" + GameInfo.UserName);
            File file = new File(GameInfo.GameDir + tpf + "versions" + tpf + version + tpf + version + ".json");
            FileReader r = new FileReader(file);
            char c[] = new char[(int) file.length()];
            r.read(c);
            jo = new JSONObject(String.valueOf(c));
            //  msg(String.valueOf(GameInfo.NotFoundedLibs.isEmpty()));
            l.Log("Calling download Thread");
            download.start();
            //      msg("开始生成启动命令行");
//Thread.yield();
          /*  while (true) {
             if (downok == true && unok == true) {
             break;
             }
             if (downok == true && unok == false) {
             downok=false;
             unzip.start();
             }

             }*/
        //    Thread.yield();

            //   Runtime.getRuntime().exec(cmd);
        } catch (IOException | JSONException | PatternSyntaxException e) {
        }
    }//GEN-LAST:event_formWindowOpened

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
// TODO add your handling code here:
        download.interrupt();
        unzip.interrupt();
        dispose();
    }//GEN-LAST:event_formWindowClosing
    private void msg(String msg) {
        jTextArea1.setText(jTextArea1.getText() + "\n" + msg);
    }
    /**
     * @param args the command line arguments
     */


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    // End of variables declaration//GEN-END:variables

    class DownloadThread implements Runnable {
        
        @Override
        public void run() {
            net.ytbolg.mcxa.Output.Logger l = new net.ytbolg.mcxa.Output.Logger(0);
            l.Log(GameInfo.NotFoundedLibs.isEmpty() ? "have not found libs" : "");
            if (GameInfo.NotFoundedLibs.isEmpty() == false) {
                d = new Downloader();
                msg(Lang.getLang("Lauch_LostLib1") + GameInfo.NotFoundedLibs.size() + Lang.getLang("Lauch_LostLib2") + "\n--------------");
                msg(Lang.getLang("Lauch_StratDownload"));
                l.Log("Not found libs:" + GameInfo.NotFoundedLibs.toString());
                for (int a = 0; a < GameInfo.NotFoundedLibs.size(); a++) {
                    d.add(DownLoadURL.getURL(DownLoadURL.LIBRARIES, Integer.valueOf(Config.getConfig("DownSou"))) + GameInfo.NotFoundedLibs.get(a), GameInfo.GameDir + tpf + "libraries" + GameInfo.NotFoundedLibs.get(a));
                    /*                    msg("下载第" + (a + 1) + "个缺失库文件:" + GameInfo.NotFoundedLibs.get(a));
                     String ab = GameInfo.downUrl + GameInfo.NotFoundedLibs.get(a);
                     ab = ab.replace(tpf, "/");
                     downloadFile(ab, GameInfo.GameDir + tpf + "libraries" + GameInfo.NotFoundedLibs.get(a));*/
                }
                
                d.start();
                d.setVisible(true);
                //d.dispose();
                //     System.out.println(GameInfo.Downok);
                int x = 0;
                while (true) {
                    x++;
                }
            }
            unzip.start();

            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    }
    
}

class unZipThread implements Runnable {
    
    public static JTextArea j;
    
    static void msg(String msg) {
        j.setText(j.getText() + "\n" + msg);
    }
    
    static void DeleteDir(File dir) {
//Enumeration e=new Enumeration();
        File f[] = dir.listFiles(new FileFilter() {
            
            @Override
            public boolean accept(File pathname) {
                if (!pathname.isDirectory()) {
                    return false;
                } else {
                    return true;
                }
                // throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        });
        for (File f1 : f) {
            f1.delete();
        }
        dir.delete();
    }
    
    @Override
    public void run() {
        boolean Checkok = true;
        try {
            //  msg(String.valueOf(ConfigClass.showlauchinfo));
            //    msg(String.valueOf(ConfigClass.ifclose));
            msg("----------------------");
            /*   if (!new File(GameInfo.GameDir + tpf + "assets" + tpf + "indexes" + tpf + version.substring(0, version.indexOf("-"))+".json").exists()) {
             msg("没找到声音索引,开始下载");
             downloadFile("http://bmclapi.bangbang93.com/indexes/" + version + ".json", GameInfo.GameDir + tpf + "assets" + tpf + "indexes" + tpf + version.substring(0, version.indexOf("-"))+".json");
             }*/
            //     msg("删除Native" + (new File(GameInfo.GameDir + tpf + "Native").delete() ? "成功" : "失败"));
            msg(Lang.getLang("Lauch_StartUnzipNative"));
//for (int g=0;g<)

            File f = new File(GameInfo.GameDir + tpf + "versions" + tpf + version + tpf + "Natives");
            if (!f.exists()) {
                f.mkdir();
            }
            if (true) {
                // System.out.println("存在");
                ArrayList al = new ArrayList();
                //   int ia;
                //System.out.println("添加列表");
                for (int i = 0; i < GameInfo.unzipAbledLibs.size(); i++) {
                    al.addAll(getZipSizes(new ZipFile(GameInfo.unzipAbledLibs.get(i).toString())));
                }
                ArrayList<File> files = new ArrayList<>();
                File templist[] = f.listFiles(new FileFilter() {
                    
                    @Override
                    public boolean accept(File pathname) {
                        if (pathname.isFile()) {
                            return true;
                        } else {
                            return false;
                        }
//       throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                    }
                });
                //  System.out.println(Arrays.toString(templist));
                if (templist.length != 0) {
                    for (int i = 0; i < templist.length; i++) {
                        files.add(templist[i]);
                    }
                    if (files.isEmpty()) {
                        Checkok = false;
                    }
                }
                ArrayList<String> names = new ArrayList<>();
                //  System.out.println(al.size());
                for (int i = 0; i < al.size(); i++) {
                    names.add(((ZipFileSize) al.get(i)).getZipEntry().getName());
                }
                //     System.out.println("检测文件" + files.size());
                ArrayList<String> fnames = new ArrayList<>();
                for (int i = 0; i < files.size(); i++) {
                    fnames.add(files.get(i).getName());
                }
                for (int i = 0; i < names.size(); i++) {
                    
                    ZipFileSize zfs = (ZipFileSize) al.get(i);
                    if (zfs.getZipEntry().getName().contains("META-INF")) {
                        continue;
                    }
                    if (fnames.contains(names.get(i)) && files.get(fnames.indexOf(names.get(i))).length() == zfs.getSize()) {
                        
                        continue;
                        
                    } else {
                        new net.ytbolg.mcxa.Output.Logger(0).Log("Unzipping:" + zfs.getZipEntry().getName());
                        File tf = new File(GameInfo.GameDir + tpf + "versions" + tpf + version + tpf + "Natives" + tpf + zfs.getZipEntry().getName());
                        tf.createNewFile();
                        msg(Lang.getLang("Lauch_UnzipFaild1") + zfs.getZipEntry().getName());
                        ZipFile zf = zfs.getZipFile();
                        InputStream is = zf.getInputStream(zfs.getZipEntry());
                        FileOutputStream fos = new FileOutputStream(tf);
                        int by;
                        while ((by = is.read()) != -1) {
                            fos.write(by);
                        }
                        is.close();
                        fos.close();
                        
                    }
                    //  zfs.getZipFile().close();
                    //    f = null;
                    // files.get(i) = null;
                }
            }/* else  {
             System.out.println("不存在");
             for (Iterator it = GameInfo.unzipAbledLibs.iterator(); it.hasNext();) {
             Object unzipAbledLib = it.next();
            
             if (!f.exists() || f.isFile()) {
             //      DeleteDir(f);
             f.mkdirs();
             }
             unZipThread.unzipFiles((unzipAbledLib.toString()), f);
             //   unzipFile(, );
             msg("----------------------");
             }
             }*/
            
            msg(Lang.getLang("Lauch_StartReplaceLauchArgs"));
            //    System.out.println(lib);
            if (GameInfo.token.equals("")) {
                GameInfo.token = "auth_access_token";
            }
            String args = MakeCmd.ReplaceArgs(LauchInfoWindow.jo.getString("minecraftArguments"), GameInfo.UserName, version, GameInfo.token, GameInfo.twitchToken);
            //      System.out.println(args);

            msg(Lang.getLang("Lauch_ForStarting"));
            String apparg = GameInfo.lauchArg;
            
            String cmd = MakeCmd.MakeCmd(LauchInfoWindow.lib, args, GameInfo.memory + "M", version, jo.getString("mainClass"), apparg);
            //    msg(jo.getString("minecraftArguments"));
            //  msg(cmd);

            boolean bl = false;
            if (Config.getConfig("showlauchinfo").equals("true")) {
                bl = true;
            }
            new net.ytbolg.mcxa.Output.Logger(0).Log("Need output lauch arg:" + bl);

            //     System.out.println(GameInfo.Rundir + tpf + "tmp." + kzm);
            //    System.out.println(System.getProperty("os.name").contains("Windows"));
            String fgf = System.getProperty("os.name").contains("Windows") ? "\"" : "'";
            final Process p;
            ProcessBuilder pb = new ProcessBuilder();
            if (System.getProperty("os.name").contains("Windows")) {
                File tmpPath = new File(GameInfo.GameDir + tpf + "lauch_files");
                if (tmpPath.exists() == false) {
                    tmpPath.mkdir();
                }
                String tmpP = tmpPath.toString() + tpf + Calendar.getInstance().getTimeInMillis() + ".bat";
                FileWriter fw = new FileWriter(tmpP);
                cmd="\"" + GameInfo.JavaPath + "\"" + cmd;
                fw.write(cmd);
                fw.close();
                p = Runtime.getRuntime().exec(tmpP);
                if (bl) {
                    msg(cmd);
                }
//   p = Runtime.getRuntime().exec(cmd);

                //     p.comm
//  pb.command(cmd);
            } else {

                //  ProcessBuilder pb = new ProcessBuilder();
                //     cmd = "'" +GameInfo.JavaPath + "' " + cmd;
                //    msg(cmd);
                /*              //  Runtime.getRuntime().exec("bash -c " + (System.getProperty("java.home") + tpf + "bin" + tpf + "java") + cmd);
                 pb.command("/bin/bash");
                 pb.command("-c");
                 pb.command(cmd);
                 // pb.directory();
                 pb.start();*/
                final String shdir = GameInfo.Rundir + "/";
                FileWriter fw = new FileWriter(shdir + "tmp.sh");
                cmd = "\"" + GameInfo.JavaPath + "\" " + cmd;
                fw.write(cmd);
                fw.close();
                Runtime.getRuntime().exec("chmod 755 " + shdir + "/tmp.sh");
                p = Runtime.getRuntime().exec("sh " + shdir + "tmp.sh");
                //  new File(shdir + "tmp.sh").delete();
                if (bl) {
                    msg(cmd);
                }

// msg(cmd);
                //   System.out.println(cmd);
                //  pb.start();
//  Runtime.getRuntime().exec("bash -c " + cmd, null, );
            }
            MCLaucherXA.l.Log("Command:" + cmd);
            if (Config.getConfig("ifclose").equals("true")) {
                System.exit(0);
//   Thread.interrupted();
            }
            if (Config.getConfig("showlauchinfo").equals("true")) {
                new Thread(new OutKeeper(p, LauchInfoWindow.jta)).start();
            }

            //  pb.start();
//  Runtime.getRuntime().exec(yxfs + GameInfo.Rundir + tpf + "tmp." + kzm);
            //  new File(GameInfo.Rundir + tpf + "tmp.sh").delete();
            //
            //   System.out.println(GameInfo.uuid);
            //    System.out.println("Making successfully");
            //   msg(cmd);
            //    Thread.
            //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        } catch (IOException | PatternSyntaxException | JSONException e) {
            JOptionPane.showMessageDialog(null, e.getMessage());
            e.printStackTrace();
        }
        
    }

    /* public static void unzipFiles(String targetPath, File zipFilePath) {
    
     try {
     //     File zipFile = new File(zipFilePath);
     InputStream is = new FileInputStream(zipFilePath);
     ZipInputStream zis = new ZipInputStream(is);
     ZipEntry entry = null;
     //   entry.
     msg(Lang.getLang("Lauch_StartUnzip") + zipFilePath.getName() + "...");
     while ((entry = zis.getNextEntry()) != null) {
     String zipPath = entry.getName();
     if (zipPath.contains("META-INF")) {
     continue;
     }
     try {
    
     if (entry.isDirectory()) {
     File zipFolder = new File(targetPath + File.separator
     + zipPath);
     if (!zipFolder.exists()) {
     zipFolder.mkdirs();
     }
     } else {
     File file = new File(targetPath + File.separator
     + zipPath);
     if (!file.exists()) {
     File pathDir = file.getParentFile();
     pathDir.mkdirs();
     file.createNewFile();
     }
    
     FileOutputStream fos = new FileOutputStream(file);
     int bread;
     while ((bread = zis.read()) != -1) {
     fos.write(bread);
     }
     fos.close();
    
     }
     msg(Lang.getLang("Lauch_UnzipSucc") + zipPath);
    
     } catch (Exception e) {
     msg(Lang.getLang("Lauch_UnzipFaild1") + zipPath + Lang.getLang("Lauch_UnzipFaild2"));
     continue;
     }
     }
     zis.close();
     is.close();
     //      System.out.println("解压结束");
     } catch (Exception e) {
     e.printStackTrace();
     }
    
     }*/
    // static long[] 
    static ArrayList getZipSizes(ZipFile zf) {
        Enumeration e = zf.entries();
        ArrayList a = new ArrayList<>();
        //    int i = 0;
        while (e.hasMoreElements()) {
            
            ZipEntry ze = (ZipEntry) e.nextElement();
            if (ze.isDirectory()) {
                continue;
            }
            a.add(new ZipFileSize(ze.getSize(), ze, zf));
            //   i++;
        }
        
        return a;
    }
    
}

class ZipFileSize {
    
    private long size = 0;
    private ZipEntry ze = null;
    private ZipFile Zf = null;
    
    public ZipFileSize(long size, ZipEntry ze, ZipFile zf) {
        this.size = size;
        this.ze = ze;
        this.Zf = zf;
    }
    
    public long getSize() {
        return size;
    }
    
    public ZipEntry getZipEntry() {
        return ze;
    }
    
    public ZipFile getZipFile() {
        return Zf;
    }
}
